﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebChatApi.Common.Interface;
using WebChatApi.Common.LightAccessControl;

namespace WebChatApi.Common
{
    /// <summary>
    /// class for base messaging util
    /// </summary>
    /// <typeparam name="TService">The type of the service.</typeparam>
    /// <typeparam name="TMessage">The type of the message.</typeparam>
    public abstract class BaseMessagingUtil<TService, TMessage> : IBaseMessagingUtil<TService, TMessage> where TService : IBaseMessagingService<TMessage>
    {
        #region Properties

        /// <summary>
        /// Gets or sets the access license.
        /// </summary>
        /// <value>
        /// The access license.
        /// </value>
        public AccessLicense AccessLicense
        {
            get;
            protected set;
        }

        /// <summary>
        /// Gets the access license access key.
        /// </summary>
        /// <value>
        /// The access license access key.
        /// </value>
        protected abstract Guid AccessLicenseAccessKey
        {
            get;
        }

        /// <summary>
        /// Gets the access license secret key.
        /// </summary>
        /// <value>
        /// The access license secret key.
        /// </value>
        protected abstract string AccessLicenseSecretKey
        {
            get;
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseMessagingUtil{TService, TMessage}"/> class.
        /// </summary>
        /// <param name="assignedAccessLicense">The assigned access license.</param>
        protected BaseMessagingUtil(AccessLicense assignedAccessLicense)
        {
            this.AccessLicense = assignedAccessLicense != null ? assignedAccessLicense : GetDefaultAccessLicense();
        }

        #endregion

        /// <summary>
        /// Gets the default access license.
        /// </summary>
        protected virtual AccessLicense GetDefaultAccessLicense()
        {
            return new AccessLicense { AccessKey = AccessLicenseAccessKey, SecretKey = AccessLicenseSecretKey };
        }

        /// <summary>
        /// Gets the message template by key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="cultureInfo">The culture info.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public MessageTemplate GetMessageTemplateByKey(string key, string cultureInfo)
        {
            MessageTemplate result = null;

            this.CheckNullObject(key, "key");
            this.CheckNullObject(cultureInfo, "cultureInfo");

            using (MessageTemplateAccessController controller = new MessageTemplateAccessController())
            {
                result = controller.GetMessageTemplateByKey(key, cultureInfo);
            }

            return result;
        }

        /// <summary>
        /// Updates the message template by key.
        /// </summary>
        /// <param name="messageTemplate">The message template.</param>
        public void UpdateMessageTemplateByKey(MessageTemplate messageTemplate)
        {
            this.CheckNullObject(messageTemplate, "messageTemplate");

            using (MessageTemplateAccessController controller = new MessageTemplateAccessController())
            {
                controller.UpdateMessageTemplateByKey(messageTemplate);
            }
        }

        /// <summary>
        /// Creates the service proxy.
        /// </summary>
        /// <param name="serviceUrl">The service URL.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public abstract TService CreateServiceProxy(string serviceUrl = null);

        /// <summary>
        /// Sends the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        public virtual MessagingResponse Send(TMessage message)
        {
            try
            {
                message.CheckNullObject("message");

                TService service = CreateServiceProxy();
                AccessLicenseBasedServiceRequest<TMessage> result = new AccessLicenseBasedServiceRequest<TMessage>();
                result.AccessLicense = this.AccessLicense;
                result.RequestDetail = message;

                return service.Send(result);
            }
            catch (BaseException bex)
            {
                throw bex.ToServiceException();
            }
            catch (Exception ex)
            {
                throw new OperationFailureException("SendMessage", ex, message);
            }
        }
    }
}
